#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <assert.h>
#include <time.h>

struct global_queue {
	uint64_t data;
	pthread_cond_t cond;
	pthread_mutex_t mutex;
};
static struct global_queue *Q;
static time_t start;
static int signal;
//#define USE_JACK_LOCK
#define ST 99999
static void *start_routine(void *param)
{
	uint64_t index = 0;
	for (;;)
	{
		Q->data = 0;
		time_t delta = time(NULL) - start;
		assert(delta < 7);
		printf("run run run, index = %lu, delta = %d\n", index++, delta);
		usleep(rand() % ST);
		if (pthread_mutex_lock(&Q->mutex) == 0)
		{
			if (Q->data == 0)
			{
				usleep(rand() % ST);
				assert(Q->data == 0 || signal == 0);
				pthread_cond_wait(&Q->cond, &Q->mutex);
			}
			if (pthread_mutex_unlock(&Q->mutex))
			{
				fprintf(stderr, "unlock mutex error");
				exit(1);
			}
		}
	}
	return NULL;
}

int main(int argc, char *argv[])
{
	srand(getpid());
	Q = (struct global_queue *)malloc(sizeof(struct global_queue));
	pthread_mutex_init(&Q->mutex, NULL);
	pthread_cond_init(&Q->cond, NULL);
	Q->data = 0;
	
	pthread_t t1;
	if (pthread_create(&t1, NULL, start_routine, NULL))
	{
		fprintf(stderr, "Create thread failed");
		exit(1);
	}

	for (;;)
	{
		start = time(NULL);
		signal  = 0;
		Q->data = 1;
		usleep(rand() % ST);
#ifdef USE_JACK_LOCK		
		if (pthread_mutex_lock(&Q->mutex) == 0)
#endif			
		{
			pthread_cond_signal(&Q->cond);
			signal = 1;
			usleep(rand() % ST);
#ifdef USE_JACK_LOCK					
			if (pthread_mutex_unlock(&Q->mutex))
			{
				fprintf(stderr, "unlock mutex error");
				exit(1);
			}
#endif			
		}
	}
	return 0;
}
